Skip to content

Comments

feat: stream tool activity to Telegram in real time#113

Open
williamlmao wants to merge 1 commit intoTinyAGI:mainfrom
williamlmao:feat/telegram-activity-streaming
Open

feat: stream tool activity to Telegram in real time#113
williamlmao wants to merge 1 commit intoTinyAGI:mainfrom
williamlmao:feat/telegram-activity-streaming

Conversation

@williamlmao
Copy link

Summary

  • When an agent uses tools (Read, Write, Bash, Grep, etc.), Telegram users now see live updates like "Read /src/index.ts" and "Ran npm test" as the agent works, instead of waiting silently for the final response
  • Claude CLI is invoked with --output-format stream-json and stdout is parsed line-by-line in real time to detect tool_use events
  • Activity summaries are sent as partial responses to the Telegram outgoing queue, which the Telegram client delivers immediately while keeping the conversation pending until the final response arrives

Changes

src/lib/invoke.ts (main change)

  • Added runClaudeCommand() which spawns the Claude CLI and streams JSONL events in real time
  • Added summarizeToolUse() to turn raw tool calls into readable strings (e.g. Read /src/index.ts, Ran npm test, Searched for "handleClick")
  • Added processClaudeEvent() to parse streaming events and detect tool_use/tool_result blocks
  • invokeAgent() now accepts an onActivity callback, returns AgentInvokeResult (text + sessionId) instead of a plain string
  • Session ID extraction from streaming events for conversation continuity

src/queue-processor.ts

  • Added writeResponse() helper that supports partial, updateType, and sessionId fields
  • Added activityEmitterForAgent() — creates a callback that writes partial activity responses to the outgoing queue when tools fire
  • Activity streaming is enabled for Telegram channel messages (streamActivitiesEnabled = channel === 'telegram')

src/channels/telegram-client.ts

  • ResponseData interface extended with sessionId, partial, updateType
  • Outgoing queue files are now sorted for consistent ordering
  • Partial (activity) responses are sent immediately but do not clear pending state — only the final response does
  • Session ID appended to final responses

src/lib/types.ts

  • ResponseData: added sessionId?, partial?, updateType? fields
  • ChainStep: added sessionId? field

Test plan

  • Send a message to the Telegram bot that triggers tool use (e.g. ask the agent to read a file or run a command)
  • Verify that activity messages appear in Telegram as tools are called (e.g. "Read /path/to/file")
  • Verify the final response still arrives normally after activities
  • Verify non-Telegram channels (Discord, WhatsApp) continue to work without activity streaming
  • Verify team chain conversations still work with activity streaming enabled

🤖 Generated with Claude Code

When an agent uses tools (Read, Write, Bash, Grep, etc.), Telegram users
now see live updates like "Read /src/index.ts" and "Ran npm test" as the
agent works, instead of waiting silently for the final response.

How it works:
- invoke.ts: Claude CLI now runs with --output-format stream-json and
  streams stdout line-by-line. Each tool_use event is parsed into a
  human-readable summary via summarizeToolUse(), and an onActivity
  callback fires immediately.
- queue-processor.ts: For Telegram messages, an activity emitter writes
  partial responses (partial: true, updateType: 'activity') to the
  outgoing queue as tools are called.
- telegram-client.ts: Partial responses are sent immediately but keep
  the message in pending state. Only the final response clears pending.
- types.ts: ResponseData gains sessionId, partial, and updateType fields.

Also extracts Claude session IDs from streaming events for conversation
continuity tracking.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

1 participant